/**
 * Copyright(c) Live2D Inc. All rights reserved.
 *
 * Use of this source code is governed by the Live2D Open Software license
 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
 */

/// <reference path="../../Core/live2dcubismcore.d.ts" />
import {Live2DCubismFramework as cubismrenderer} from "../rendering/cubismrenderer";
import {Live2DCubismFramework as cubismid} from "../id/cubismid";
import {Live2DCubismFramework as cubismframework} from "../live2dcubismframework";
import {Live2DCubismFramework as csmmap} from "../type/csmmap";
import {Live2DCubismFramework as csmvector} from "../type/csmvector";
import {CSM_ASSERT} from "../utils/cubismdebug";
import CubismFramework = cubismframework.CubismFramework;
import CubismBlendMode = cubismrenderer.CubismBlendMode;
import csmVector = csmvector.csmVector;
import csmMap = csmmap.csmMap;
import CubismIdHandle = cubismid.CubismIdHandle;

export namespace Live2DCubismFramework
{
    /**
     * モデル
     *
     * Mocデータから生成されるモデルのクラス。
     */
    export class CubismModel
    {
        /**
         * モデルのパラメータの更新
         */
        public update(): void
        {
            // Update model
            this._model.update();

            this._model.drawables.resetDynamicFlags();
        }

        /**
         * キャンバスの幅を取得する
         */
        public getCanvasWidth(): number
        {
            if (this._model == null)
            {
                return 0.0;
            }

            return this._model.canvasinfo.CanvasWidth / this._model.canvasinfo.PixelsPerUnit;
        }

        /**
         * キャンバスの高さを取得する
         */
        public getCanvasHeight(): number
        {
            if (this._model == null)
            {
                return 0.0;
            }

            return this._model.canvasinfo.CanvasHeight / this._model.canvasinfo.PixelsPerUnit;
        }

        /**
         * パラメータを保存する
         */
        public saveParameters(): void
        {
            const parameterCount: number = this._model.parameters.count;
            const savedParameterCount: number = this._savedParameters.getSize();

            for (let i: number = 0; i < parameterCount; ++i)
            {
                if (i < savedParameterCount)
                {
                    this._savedParameters.set(i, this._parameterValues[i]);
                }
                else
                {
                    this._savedParameters.pushBack(this._parameterValues[i]);
                }
            }
        }

        /**
         * モデルを取得
         */
        public getModel(): Live2DCubismCore.Model
        {
            return this._model;
        }

        /**
         * パーツのインデックスを取得
         * @param partId パーツのID
         * @return パーツのインデックス
         */
        public getPartIndex(partId: CubismIdHandle): number
        {
            let partIndex: number;
            const partCount: number = this._model.parts.count;

            for(partIndex = 0; partIndex < partCount; ++partIndex)
            {
                if(partId == this._partIds.at(partIndex))
                {
                    return partIndex;
                }
            }

            // モデルに存在していない場合、非存在パーツIDリスト内にあるかを検索し、そのインデックスを返す
            if(this._notExistPartId.isExist(partId))
            {
                return this._notExistPartId.getValue(partId);
            }

            // 非存在パーツIDリストにない場合、新しく要素を追加する
            partIndex = partCount + this._notExistPartId.getSize();
            this._notExistPartId.setValue(partId, partIndex);
            this._notExistPartOpacities.appendKey(partIndex);

            return partIndex;
        }

        /**
         * パーツの個数の取得
         * @return パーツの個数
         */
        public getPartCount(): number
        {
            const partCount: number = this._model.parts.count;
            return partCount;
        }

        /**
         * パーツの不透明度の設定(Index)
         * @param partIndex パーツのインデックス
         * @param opacity 不透明度
         */
        public setPartOpacityByIndex(partIndex: number, opacity: number): void
        {
            if(this._notExistPartOpacities.isExist(partIndex))
            {
                this._notExistPartOpacities.setValue(partIndex,opacity);
                return;
            }

            // インデックスの範囲内検知
            CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount());

            this._partOpacities[partIndex] = opacity;
        }

        /**
         * パーツの不透明度の設定(Id)
         * @param partId パーツのID
         * @param opacity パーツの不透明度
         */
        public setPartOpacityById(partId: CubismIdHandle, opacity: number): void
        {
            // 高速化のためにPartIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要
            const index: number = this.getPartIndex(partId);

            if(index < 0)
            {
                return; // パーツがないのでスキップ
            }

            this.setPartOpacityByIndex(index, opacity);
        }

        /**
         * パーツの不透明度の取得(index)
         * @param partIndex パーツのインデックス
         * @return パーツの不透明度
         */
        public getPartOpacityByIndex(partIndex: number): number
        {
            if(this._notExistPartOpacities.isExist(partIndex))
            {
                // モデルに存在しないパーツIDの場合、非存在パーツリストから不透明度を返す。
                return this._notExistPartOpacities.getValue(partIndex);
            }

            // インデックスの範囲内検知
            CSM_ASSERT(0 <= partIndex && partIndex < this.getPartCount());

            return this._partOpacities[partIndex];
        }

        /**
         * パーツの不透明度の取得(id)
         * @param partId パーツのＩｄ
         * @return パーツの不透明度
         */
        public getPartOpacityById(partId: CubismIdHandle): number
        {
            // 高速化のためにPartIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要
            const index: number = this.getPartIndex(partId);

            if(index < 0)
            {
                return 0;   // パーツが無いのでスキップ
            }

            return this.getPartOpacityByIndex(index);
        }

        /**
         * パラメータのインデックスの取得
         * @param パラメータID
         * @return パラメータのインデックス
         */
        public getParameterIndex(parameterId: CubismIdHandle): number
        {
            let parameterIndex: number;
            const idCount: number = this._model.parameters.count;

            for(parameterIndex = 0; parameterIndex < idCount; ++parameterIndex)
            {
                if(parameterId != this._parameterIds.at(parameterIndex))
                {
                    continue;
                }

                return parameterIndex;
            }

            // モデルに存在していない場合、非存在パラメータIDリスト内を検索し、そのインデックスを返す
            if(this._notExistParameterId.isExist(parameterId))
            {
                return this._notExistParameterId.getValue(parameterId);
            }

            // 非存在パラメータIDリストにない場合新しく要素を追加する
            parameterIndex = this._model.parameters.count + this._notExistParameterId.getSize();

            this._notExistParameterId.setValue(parameterId, parameterIndex);
            this._notExistParameterValues.appendKey(parameterIndex);

            return parameterIndex;
        }

        /**
         * パラメータの個数の取得
         * @return パラメータの個数
         */
        public getParameterCount(): number
        {
            return this._model.parameters.count;
        }

        /**
         * パラメータの最大値の取得
         * @param parameterIndex パラメータのインデックス
         * @return パラメータの最大値
         */
        public getParameterMaximumValue(parameterIndex: number): number
        {
            return this._model.parameters.maximumValues[parameterIndex];
        }

        /**
         * パラメータの最小値の取得
         * @param parameterIndex パラメータのインデックス
         * @return パラメータの最小値
         */
        public getParameterMinimumValue(parameterIndex: number): number
        {
            return this._model.parameters.minimumValues[parameterIndex];
        }

        /**
         * パラメータのデフォルト値の取得
         * @param parameterIndex パラメータのインデックス
         * @return パラメータのデフォルト値
         */
        public getParameterDefaultValue(parameterIndex: number): number
        {
            return this._model.parameters.defaultValues[parameterIndex];
        }

        /**
         * パラメータの値の取得
         * @param parameterIndex    パラメータのインデックス
         * @return パラメータの値
         */
        public getParameterValueByIndex(parameterIndex: number): number
        {
            if(this._notExistParameterValues.isExist(parameterIndex))
            {
                return this._notExistParameterValues.getValue(parameterIndex);
            }

            // インデックスの範囲内検知
            CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount());

            return this._parameterValues[parameterIndex];
        }

        /**
         * パラメータの値の取得
         * @param parameterId    パラメータのID
         * @return パラメータの値
         */
        public getParameterValueById(parameterId: CubismIdHandle): number
        {
            // 高速化のためにparameterIndexを取得できる機構になっているが、外部からの設定の時は呼び出し頻度が低いため不要
            const parameterIndex: number = this.getParameterIndex(parameterId);
            return this.getParameterValueByIndex(parameterIndex);
        }

        /**
         * パラメータの値の設定
         * @param parameterIndex パラメータのインデックス
         * @param value パラメータの値
         * @param weight 重み
         */
        public setParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void
        {
            if(this._notExistParameterValues.isExist(parameterIndex))
            {
                this._notExistParameterValues.setValue(
                    parameterIndex,
                    (weight == 1)
                        ? value
                        : (this._notExistParameterValues.getValue(parameterIndex) * (1 - weight)) + (value * weight)
                );

                return;
            }

            // インデックスの範囲内検知
            CSM_ASSERT(0 <= parameterIndex && parameterIndex < this.getParameterCount());

            if(this._model.parameters.maximumValues[parameterIndex] < value)
            {
                value = this._model.parameters.maximumValues[parameterIndex];
            }
            if(this._model.parameters.minimumValues[parameterIndex] > value)
            {
                value = this._model.parameters.minimumValues[parameterIndex];
            }

            this._parameterValues[parameterIndex] = (weight == 1)
                                                    ? value
                                                    : this._parameterValues[parameterIndex] = (this._parameterValues[parameterIndex] * (1 - weight)) + (value * weight);
        }

        /**
         * パラメータの値の設定
         * @param parameterId パラメータのID
         * @param value パラメータの値
         * @param weight 重み
         */
        public setParameterValueById(parameterId: CubismIdHandle, value: number, weight: number = 1.0): void
        {
            const index: number = this.getParameterIndex(parameterId);
            this.setParameterValueByIndex(index, value, weight);
        }

        /**
         * パラメータの値の加算(index)
         * @param parameterIndex パラメータインデックス
         * @param value 加算する値
         * @param weight 重み
         */
        public addParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void
        {
            this.setParameterValueByIndex(parameterIndex, (this.getParameterValueByIndex(parameterIndex) + (value * weight)));
        }

        /**
         * パラメータの値の加算(id)
         * @param parameterId パラメータＩＤ
         * @param value 加算する値
         * @param weight 重み
         */
        public addParameterValueById(parameterId: any, value: number, weight: number = 1.0): void
        {
            const index: number = this.getParameterIndex(parameterId);
            this.addParameterValueByIndex(index, value, weight);
        }

        /**
         * パラメータの値の乗算
         * @param parameterId パラメータのID
         * @param value 乗算する値
         * @param weight 重み
         */
        public multiplyParameterValueById(parameterId: CubismIdHandle, value: number, weight: number = 1.0): void
        {
            const index: number = this.getParameterIndex(parameterId);
            this.multiplyParameterValueByIndex(index, value, weight);
        }

        /**
         * パラメータの値の乗算
         * @param parameterIndex パラメータのインデックス
         * @param value　乗算する値
         * @param weight 重み
         */
        public multiplyParameterValueByIndex(parameterIndex: number, value: number, weight: number = 1.0): void
        {
            this.setParameterValueByIndex(parameterIndex, (this.getParameterValueByIndex(parameterIndex) * (1.0 + (value - 1.0) * weight)));
        }


        /**
         * Drawableのインデックスの取得
         * @param drawableId DrawableのID
         * @return Drawableのインデックス
         */
        public getDrawableIndex(drawableId: CubismIdHandle): number
        {
            const drawableCount = this._model.drawables.count;

            for(let drawableIndex: number = 0; drawableIndex < drawableCount; ++drawableIndex)
            {
                if(this._drawableIds.at(drawableIndex) == drawableId)
                {
                    return drawableIndex;
                }
            }

            return -1;
        }

        /**
         * Drawableの個数の取得
         * @return drawableの個数
         */
        public getDrawableCount(): number
        {
            const drawableCount = this._model.drawables.count;
            return drawableCount;
        }

        /**
         * DrawableのIDを取得する
         * @param drawableIndex Drawableのインデックス
         * @return drawableのID
         */
        public getDrawableId(drawableIndex: number): CubismIdHandle
        {
            const parameterIds: string[] = this._model.drawables.ids;
            return CubismFramework.getIdManager().getId(parameterIds[drawableIndex]);
        }

        /**
         * Drawableの描画順リストの取得
         * @return Drawableの描画順リスト
         */
        public getDrawableRenderOrders(): Int32Array
        {
            const renderOrders: Int32Array = this._model.drawables.renderOrders;
            return renderOrders;
        }

        /**
         * Drawableのテクスチャインデックスリストの取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableのテクスチャインデックスリスト
         */
        public getDrawableTextureIndices(drawableIndex: number): number
        {
            const textureIndices: Int32Array = this._model.drawables.textureIndices;
            return textureIndices[drawableIndex];
        }

        /**
         * DrawableのVertexPositionsの変化情報の取得
         *
         * 直近のCubismModel.update関数でDrawableの頂点情報が変化したかを取得する。
         *
         * @param   drawableIndex   Drawableのインデックス
         * @retval  true    Drawableの頂点情報が直近のCubismModel.update関数で変化した
         * @retval  false   Drawableの頂点情報が直近のCubismModel.update関数で変化していない
         */
        public getDrawableDynamicFlagVertexPositionsDidChange(drawableIndex: number): boolean
        {
            const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags;
            return Live2DCubismCore.Utils.hasVertexPositionsDidChangeBit(dynamicFlags[drawableIndex]);
        }

        /**
         * Drawableの頂点インデックスの個数の取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableの頂点インデックスの個数
         */
        public getDrawableVertexIndexCount(drawableIndex: number): number
        {
            const indexCounts: Int32Array = this._model.drawables.indexCounts;
            return indexCounts[drawableIndex];
        }

        /**
         * Drawableの頂点の個数の取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableの頂点の個数
         */
        public getDrawableVertexCount(drawableIndex: number): number
        {
            const vertexCounts = this._model.drawables.vertexCounts;
            return vertexCounts[drawableIndex];
        }

        /**
         * Drawableの頂点リストの取得
         * @param drawableIndex drawableのインデックス
         * @return drawableの頂点リスト
         */
        public getDrawableVertices(drawableIndex: number): Float32Array
        {
            return this.getDrawableVertexPositions(drawableIndex);
        }

        /**
         * Drawableの頂点インデックスリストの取得
         * @param drarableIndex Drawableのインデックス
         * @return drawableの頂点インデックスリスト
         */
        public getDrawableVertexIndices(drawableIndex: number): Uint16Array
        {
            const indicesArray: Uint16Array[] = this._model.drawables.indices;
            return indicesArray[drawableIndex];
        }

        /**
         * Drawableの頂点リストの取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableの頂点リスト
         */
        public getDrawableVertexPositions(drawableIndex: number): Float32Array
        {
            const verticesArray: Float32Array[] = this._model.drawables.vertexPositions;
            return verticesArray[drawableIndex];
        }

        /**
         * Drawableの頂点のUVリストの取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableの頂点UVリスト
         */
        public getDrawableVertexUvs(drawableIndex: number): Float32Array
        {
            const uvsArray: Float32Array[] = this._model.drawables.vertexUvs;
            return uvsArray[drawableIndex];
        }

        /**
         * Drawableの不透明度の取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableの不透明度
         */
        public getDrawableOpacity(drawableIndex: number): number
        {
            const opacities: Float32Array = this._model.drawables.opacities;
            return opacities[drawableIndex];
        }

        /**
         * Drawableのカリング情報の取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableのカリング情報
         */
        public getDrawableCulling(drawableIndex: number): boolean
        {
            const constantFlags = this._model.drawables.constantFlags;

            return !Live2DCubismCore.Utils.hasIsDoubleSidedBit(constantFlags[drawableIndex]);
        }

        /**
         * Drawableのブレンドモードを取得
         * @param drawableIndex Drawableのインデックス
         * @return drawableのブレンドモード
         */
        public getDrawableBlendMode(drawableIndex: number): CubismBlendMode
        {
            const constantFlags = this._model.drawables.constantFlags;

            return (Live2DCubismCore.Utils.hasBlendAdditiveBit(constantFlags[drawableIndex]))
                        ? CubismBlendMode.CubismBlendMode_Additive
                        : (Live2DCubismCore.Utils.hasBlendMultiplicativeBit(constantFlags[drawableIndex]))
                        ? CubismBlendMode.CubismBlendMode_Multiplicative
                        : CubismBlendMode.CubismBlendMode_Normal;
        }

        /**
         * Drawableのマスクの反転使用の取得
         *
         * Drawableのマスク使用時の反転設定を取得する。
         * マスクを使用しない場合は無視される。
         *
         * @param drawableIndex Drawableのインデックス
         * @return Drawableの反転設定
         */
        public getDrawableInvertedMaskBit(drawableIndex: number): boolean
        {
            const constantFlags: Uint8Array = this._model.drawables.constantFlags;

            return (Live2DCubismCore.Utils.hasIsInvertedMaskBit(constantFlags[drawableIndex]));
        }

        /**
         * Drawableのクリッピングマスクリストの取得
         * @return Drawableのクリッピングマスクリスト
         */
        public getDrawableMasks(): Int32Array[]
        {
            const masks: Int32Array[] = this._model.drawables.masks;
            return masks;
        }

        /**
         * Drawableのクリッピングマスクの個数リストの取得
         * @return Drawableのクリッピングマスクの個数リスト
         */
        public getDrawableMaskCounts(): Int32Array
        {
            const maskCounts: Int32Array = this._model.drawables.maskCounts;
            return maskCounts;
        }

        /**
         * クリッピングマスクの使用状態
         *
         * @return true クリッピングマスクを使用している
         * @return false クリッピングマスクを使用していない
         */
        public isUsingMasking(): boolean
        {
            for(let d: number = 0; d < this._model.drawables.count; ++d)
            {
                if(this._model.drawables.maskCounts[d] <= 0)
                {
                    continue;
                }
                return true;
            }
            return false;
        }

        /**
         * Drawableの表示情報を取得する
         *
         * @param drawableIndex Drawableのインデックス
         * @return true Drawableが表示
         * @return false Drawableが非表示
         */
        public getDrawableDynamicFlagIsVisible(drawableIndex: number): boolean
        {
            const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags;
            return Live2DCubismCore.Utils.hasIsVisibleBit(dynamicFlags[drawableIndex]);
        }

        /**
         * DrawableのDrawOrderの変化情報の取得
         *
         * 直近のCubismModel.update関数でdrawableのdrawOrderが変化したかを取得する。
         * drawOrderはartMesh上で指定する0から1000の情報
         * @param drawableIndex drawableのインデックス
         * @return true drawableの不透明度が直近のCubismModel.update関数で変化した
         * @return false drawableの不透明度が直近のCubismModel.update関数で変化している
         */
        public getDrawableDynamicFlagVisibilityDidChange(drawableIndex: number): boolean
        {
            const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags;
            return Live2DCubismCore.Utils.hasVisibilityDidChangeBit(dynamicFlags[drawableIndex]);
        }

        /**
         * Drawableの不透明度の変化情報の取得
         *
         * 直近のCubismModel.update関数でdrawableの不透明度が変化したかを取得する。
         *
         * @param drawableIndex drawableのインデックス
         * @return true Drawableの不透明度が直近のCubismModel.update関数で変化した
         * @return false Drawableの不透明度が直近のCubismModel.update関数で変化してない
         */
        public getDrawableDynamicFlagOpacityDidChange(drawableIndex: number): boolean
        {
            const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags;
            return Live2DCubismCore.Utils.hasOpacityDidChangeBit(dynamicFlags[drawableIndex]);
        }

        /**
         * Drawableの描画順序の変化情報の取得
         *
         * 直近のCubismModel.update関数でDrawableの描画の順序が変化したかを取得する。
         *
         * @param drawableIndex Drawableのインデックス
         * @return true Drawableの描画の順序が直近のCubismModel.update関数で変化した
         * @return false Drawableの描画の順序が直近のCubismModel.update関数で変化してない
         */
        public getDrawableDynamicFlagRenderOrderDidChange(drawableIndex: number): boolean
        {
            const dynamicFlags: Uint8Array = this._model.drawables.dynamicFlags;
            return Live2DCubismCore.Utils.hasRenderOrderDidChangeBit(dynamicFlags[drawableIndex]);
        }

        /**
         * 保存されたパラメータの読み込み
         */
        public loadParameters(): void
        {
            let parameterCount: number = this._model.parameters.count;
            const savedParameterCount: number = this._savedParameters.getSize();

            if(parameterCount > savedParameterCount)
            {
                parameterCount = savedParameterCount;
            }

            for(let i: number = 0; i < parameterCount; ++i)
            {
                this._parameterValues[i] = this._savedParameters.at(i);
            }
        }

        /**
         * 初期化する
         */
        public initialize(): void
        {
            CSM_ASSERT(this._model);

            this._parameterValues = this._model.parameters.values;
            this._partOpacities = this._model.parts.opacities;
            this._parameterMaximumValues = this._model.parameters.maximumValues;
            this._parameterMinimumValues = this._model.parameters.minimumValues;

            {
                const parameterIds: string[] = this._model.parameters.ids;
                const parameterCount: number = this._model.parameters.count;

                this._parameterIds.prepareCapacity(parameterCount);
                for(let i: number = 0; i < parameterCount; ++i)
                {
                    this._parameterIds.pushBack(CubismFramework.getIdManager().getId(parameterIds[i]));
                }
            }

            {
                const partIds: string[] = this._model.parts.ids;
                const partCount: number = this._model.parts.count;

                this._partIds.prepareCapacity(partCount);
                for(let i: number = 0; i < partCount; ++i)
                {
                    this._partIds.pushBack(CubismFramework.getIdManager().getId(partIds[i]));
                }
            }

            {
                const drawableIds: string[] = this._model.drawables.ids;
                const drawableCount: number = this._model.drawables.count;

                this._drawableIds.prepareCapacity(drawableCount);
                for(let i: number = 0; i < drawableCount; ++i)
                {
                    this._drawableIds.pushBack(CubismFramework.getIdManager().getId(drawableIds[i]));
                }
            }
        }

        /**
         * コンストラクタ
         * @param model モデル
         */
        public constructor(model: Live2DCubismCore.Model)
        {
            this._model = model;
            this._parameterValues = null;
            this._parameterMaximumValues = null;
            this._parameterMinimumValues = null;
            this._partOpacities = null;
            this._savedParameters = new csmVector<number>();
            this._parameterIds = new csmVector<CubismIdHandle>();
            this._drawableIds = new csmVector<CubismIdHandle>();
            this._partIds = new csmVector<CubismIdHandle>();

            this._notExistPartId = new csmMap<CubismIdHandle, number>();
            this._notExistParameterId = new csmMap<CubismIdHandle, number>();
            this._notExistParameterValues = new csmMap<number, number>();
            this._notExistPartOpacities = new csmMap<number, number>();
        }

        /**
         * デストラクタ相当の処理
         */
        public release(): void
        {
            this._model.release();
            this._model = null;
        }

        private _notExistPartOpacities: csmMap<number, number>; // 存在していないパーツの不透明度のリスト
        private _notExistPartId: csmMap<CubismIdHandle, number>;  // 存在していないパーツIDのリスト

        private _notExistParameterValues: csmMap<number, number>;   // 存在していないパラメータの値のリスト
        private _notExistParameterId: csmMap<CubismIdHandle, number>; // 存在していないパラメータIDのリスト

        private _savedParameters: csmVector<number>;            // 保存されたパラメータ

        private _model: Live2DCubismCore.Model;             // モデル

        private _parameterValues: Float32Array;            // パラメータの値のリスト
        private _parameterMaximumValues: Float32Array;     // パラメータの最大値のリスト
        private _parameterMinimumValues: Float32Array;     // パラメータの最小値のリスト

        private _partOpacities: Float32Array;                     // パーツの不透明度のリスト

        private _parameterIds: csmVector<CubismIdHandle>;
        private _partIds: csmVector<CubismIdHandle>;
        private _drawableIds: csmVector<CubismIdHandle>;
    }
}
